package com.webex.ta.hydra.gui.util;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-10-19
 * Time: 13:55:19
 */
public class ThreeSplitPane extends JPanel {
    private static final int DIVIDER_WIDTH = 7;
    private boolean isVertical;
    private Divider firstDivider, lastDivider;
    private JComponent firstComponent, lastComponent, innerComponent;
    private int firstSize = 10;
    private int lastSize = 10;

    public ThreeSplitPane() {
        this(false);
    }

    public ThreeSplitPane(boolean vertical) {
        isVertical = vertical;
        firstDivider = new Divider(true);
        lastDivider = new Divider(false);
        setOpaque(false);
        add(firstDivider);
        add(lastDivider);
    }

    public boolean isVertical() {
        return isVertical;
    }

    @Override
    public void doLayout() {
        final int width = getWidth();
        final int height = getHeight();

        Rectangle firstRect = new Rectangle();
        Rectangle firstDividerRect = new Rectangle();
        Rectangle lastDividerRect = new Rectangle();
        Rectangle lastRect = new Rectangle();
        Rectangle innerRect = new Rectangle();

        final int componentSize = isVertical() ? height : width;
        int dividerCount = visibleDividerCount();

        int firstComponentSize, lastComponentSize, innerComponentSize;
        if (componentSize <= DIVIDER_WIDTH * dividerCount) {
            firstComponentSize = 0;
            lastComponentSize = 0;
            innerComponentSize = 0;
        } else {
            firstComponentSize = getFirstSize();
            lastComponentSize = getLastSize();
            int  sizeLack = firstComponentSize + lastComponentSize - (componentSize - DIVIDER_WIDTH * dividerCount);
            if (sizeLack > 0) {
                // Lacking size, reduce first component's size, inner-> empty
                firstComponentSize -= sizeLack;
                innerComponentSize = 0;
            } else {
                innerComponentSize = componentSize - DIVIDER_WIDTH * dividerCount - firstComponentSize - lastComponentSize;
            }

            if (!innerVisible()) {
                lastComponentSize += innerComponentSize;
                innerComponentSize = 0;
                if (!lastVisible()) {
                    firstComponentSize = componentSize;
                }
            }
        }

        if (isVertical) {
            // VERTICAL
            int space = firstComponentSize;
            firstRect.setBounds(0,0,width, firstComponentSize);
            if (firstDividerVisible()) {
                firstDividerRect.setBounds(0,space, width, DIVIDER_WIDTH);
                space += DIVIDER_WIDTH;
            }

            innerRect.setBounds(0, space, width, innerComponentSize);
            space += innerComponentSize;

            if (lastDividerVisible()) {
                lastDividerRect.setBounds(0, space, width, DIVIDER_WIDTH);
                space += DIVIDER_WIDTH;
            }

            lastRect.setBounds(0, space, width, lastComponentSize);
        } else {
            // HORIZONTAL
            int space = firstComponentSize;
            firstRect.setBounds(0,0,firstComponentSize, height);

            if (firstDividerVisible()) {
                firstDividerRect.setBounds(space, 0, DIVIDER_WIDTH, height);
                space += DIVIDER_WIDTH;
            }

            innerRect.setBounds(space, 0, innerComponentSize, height);
            space += innerComponentSize;

            if (lastDividerVisible()) {
                lastDividerRect.setBounds(space, 0, DIVIDER_WIDTH, height);
                space += DIVIDER_WIDTH;
            }

            lastRect.setBounds(space, 0, lastComponentSize, height);
        }

        firstDivider.setVisible(firstDividerVisible());
        firstDivider.setBounds(firstDividerRect);
        firstDivider.doLayout();

        lastDivider.setVisible(lastDividerVisible());
        lastDivider.setBounds(lastDividerRect);
        lastDivider.doLayout();

        validateIfNeeded(firstComponent, firstRect);
        validateIfNeeded(innerComponent, innerRect);
        validateIfNeeded(lastComponent, lastRect);
    }

    public void setFirstComponent(JComponent c) {
        if (firstComponent != c) {
            if (firstComponent != null)
                remove(firstComponent);

            firstComponent = c;
            if (firstComponent != null) {
                add(firstComponent);
                firstComponent.invalidate();
                if (isVertical)
                    setFirstSize(firstComponent.getPreferredSize().height);
                else
                    setFirstSize(firstComponent.getPreferredSize().width);
            }
        }
    }

    public void setLastComponent(JComponent c) {
        if (lastComponent != c) {
            if (lastComponent != null)
                remove(lastComponent);

            lastComponent = c;
            if (lastComponent != null) {
                add(lastComponent);
                lastComponent.invalidate();
                if (isVertical)
                    setLastSize(lastComponent.getPreferredSize().height);
                else
                    setLastSize(lastComponent.getPreferredSize().width);
            }
        }
    }

    public void setInnerComponent(JComponent c) {
        if (innerComponent != c) {
            if (innerComponent != null)
                remove(innerComponent);

            innerComponent = c;
            if (innerComponent != null) {
                add(innerComponent);
                innerComponent.invalidate();
            }
        }
    }

    private int visibleDividerCount() {
        int count = 0;
        if (firstDividerVisible()) count++;
        if (lastDividerVisible()) count++;
        return count;
    }

    private boolean firstDividerVisible() {
        return firstVisible() && innerVisible() || firstVisible() && lastVisible() && !innerVisible();
    }

    private boolean lastDividerVisible() {
        return innerVisible() && lastVisible();
    }

    private boolean firstVisible() {
        return firstComponent != null && firstComponent.isVisible();
    }

    private boolean lastVisible() {
        return lastComponent != null && lastComponent.isVisible();
    }

    private boolean innerVisible() {
        return innerComponent != null && innerComponent.isVisible();
    }

    public void setFirstSize(int size) {
        firstSize = size;
        doLayout();
        repaint();
    }

    public int getFirstSize() {
        return firstVisible() ? firstSize : 0;
    }

    public void setLastSize(int size) {
        lastSize = size;
        doLayout();
        repaint();
    }

    public int getLastSize() {
        return lastVisible() ? lastSize : 0;
    }

    private static void validateIfNeeded(final JComponent c, final Rectangle rect) {
        if (c != null) {
            if (!c.getBounds().equals(rect)) {
                c.setBounds(rect);
                c.revalidate();
            }
        }
    }

    private class Divider extends JPanel {
        private boolean dragging = false;
        private Point lastPt;
        private boolean isFirst;


        public Divider(boolean isFirst) {
            this.isFirst = isFirst;
            setFocusable(false);
            enableEvents(MouseEvent.MOUSE_EVENT_MASK | MouseEvent.MOUSE_MOTION_EVENT_MASK);
        }

        @Override
        protected void processMouseMotionEvent(MouseEvent e) {
            super.processMouseMotionEvent(e);

            if (!isShowing()) return;

            if (e.getID() == MouseEvent.MOUSE_MOVED) {
                setCursor(isVertical ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) :
                    Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
                e.consume();
            } else if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
                dragging = true;
                lastPt = SwingUtilities.convertPoint(this, e.getPoint(), ThreeSplitPane.this);
                if (isVertical) {
                    if (isFirst)
                        setFirstSize(lastPt.y);
                    else
                        setLastSize(ThreeSplitPane.this.getHeight() - lastPt.y - DIVIDER_WIDTH);

                } else {
                    if (isFirst)  {
                        setFirstSize(lastPt.x);
                    } else {
                        setLastSize(ThreeSplitPane.this.getWidth() - lastPt.x - DIVIDER_WIDTH);
                    }
                }
            }
        }

//        @Override
//        public void paint(Graphics g) {
//            g.setColor(Color.black);
//            g.fillRect(0,0,getWidth(), getHeight());
//        }
    }
}
